﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LoginViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the LoginViewModel type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Windows.Client.ViewModel
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Windows;
    using Hisaab.Business.Interfaces;
    using Hisaab.Windows.Common;

    using Microsoft.Practices.ServiceLocation;

    using Model;

    /// <summary>
    /// Defines the <seealso cref="Hisaab.Windows.Client.ViewModel.LoginViewModel"/> type.
    /// </summary>
    public class LoginViewModel : DialogViewModel
    {
        /// <summary>
        /// User manager object
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// Represents currect session
        /// </summary>
        private readonly ISession _session;

        /// <summary>
        /// Private instance for action to do after the login is successful
        /// </summary>
        private readonly Action _afterLoginAction;

        /// <summary>
        /// Backing field for user
        /// </summary>
        private User _user;

        /// <summary>
        /// Backing field for error
        /// </summary>
        private string _error = string.Empty;

        /// <summary>
        /// Backing field for show error
        /// </summary>
        private bool _showError;

        /// <summary>
        /// Backing field for version
        /// </summary>
        private string _version;

        /// <summary>
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class.
        /// </summary>
        public LoginViewModel()
            : this(null, ServiceLocator.Current.GetInstance<IUserManager>(), ServiceLocator.Current.GetInstance<ISession>(), null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class.
        /// </summary>
        /// <param name="afterLoginAction">The after login action.</param>
        public LoginViewModel(Action afterLoginAction)
            : this(null, ServiceLocator.Current.GetInstance<IUserManager>(), ServiceLocator.Current.GetInstance<ISession>(), afterLoginAction)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class.
        /// </summary>
        /// <param name="user">The user to login</param>
        /// <param name="userManager">User manager to use</param>
        /// <param name="session">The Session</param>
        public LoginViewModel(User user, IUserManager userManager, ISession session)
            : this(user, userManager, session, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class.
        /// </summary>
        /// <param name="user">The user to login</param>
        /// <param name="userManager">User manager to use</param>
        /// <param name="session">The session.</param>
        /// <param name="afterLoginAction">
        /// The after to perform after login succeeds.
        /// </param>
        public LoginViewModel(User user, IUserManager userManager, ISession session, Action afterLoginAction)
        {
            Contract.Requires<ArgumentNullException>(userManager != null);
            Contract.Requires<ArgumentNullException>(session != null);

            _afterLoginAction = afterLoginAction;
            User = user;
            Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            _userManager = userManager;
            _session = session;
            ResizeMode = ResizeMode.NoResize;
            WindowStyle = WindowStyle.None;
            WindowStartupLocation = WindowStartupLocation.CenterScreen;
        }

        /// <summary>
        /// Gets or sets the version.
        /// </summary>
        /// <value>
        /// The version.
        /// </value>
        public string Version
        {
            get
            {
                return _version;
            }

            set
            {
                _version = value;
                OnPropertyChanged("Version");
            }
        }

        /// <summary>
        /// Gets or sets the user.
        /// </summary>
        /// <value>
        /// The user for this view model
        /// </value>
        public User User
        {
            get
            {
                return _user;
            }

            set
            {
                _user = value;
                OnPropertyChanged("User");
            }
        }

        /// <summary>
        /// Gets or sets the error.
        /// </summary>
        /// <value>
        /// The error message
        /// </value>
        public string Error
        {
            get
            {
                return _error;
            }

            set
            {
                _error = value;
                OnPropertyChanged("Error");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show error].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [show error]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowError
        {
            get
            {
                return _showError;
            }
            set
            {
                _showError = value;
                OnPropertyChanged("ShowError");
            }
        }

        /// <summary>
        /// Called when [ok pressed].
        /// </summary>
        /// <returns>
        /// True if dialog to be closed, false to avoid closing
        /// </returns>
        public override bool? OnOkDialog()
        {
            Busy = true;
            try
            {
                ShowError = false;
                var userId = _userManager.ValidateUser(User.Username, User.Password);
                if (userId < 0)
                {
                    Error = "Invalid username or password!";
                    ShowError = true;
                    return null;
                }

                if (_afterLoginAction != null)
                {
                    _session.LoggedUser = userId;
                    _afterLoginAction();
                }
            }
            finally
            {
                Busy = false;
            }

            return true;
        }
    }
}